package com.qf.agro.utils;


import com.qf.agro.common.sys.SysUserHolder;
import com.qf.agro.pojo.sys.SysLog;
import com.qf.agro.pojo.sys.SysUser;
import com.qf.agro.service.sys.SysLogService;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @company：千锋教育
 * @author：zhy
 * @date：2023/7/4
 *
 * 记录日志的切面类
 */
@Component
@Aspect
public class LogAspect {

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    private HttpServletRequest request;

    /**
     * 环绕通知记录日志
     * @param pjp
     * @return
     */
    @Around("execution(* com.qf.agro.web.controller.*.*.*(..))")
    public Object logAroundAdvice(ProceedingJoinPoint pjp){
        //1.定义返回值
        Object rtValue = null;
        try {
            //取出当前线程上的用户
            SysUser user = SysUserHolder.get();
            if(user != null) {
                //创建日志对象
                SysLog sysLog = new SysLog();
                //设置值
                sysLog.setUsername(user.getUsername());
                sysLog.setCompanyId(user.getCompanyId());
                sysLog.setCompanyName(user.getCompanyName());
                sysLog.setCreateTime(new Date());
                sysLog.setIp(request.getRemoteAddr());


                //pjp里面有一个签名
                //取出签名
                Signature signature = pjp.getSignature();//他其实就是方法签名
                //把他强转成方法的签名
                MethodSignature methodSignature = (MethodSignature) signature;
                //取出签名所对应的方法
                Method method = methodSignature.getMethod();
                //取出当前方法声明在哪个类中
                Class<?> declaringClass = method.getDeclaringClass();

                sysLog.setMethod(/*declaringClass.getName()+"::"+*/method.getName());

                String action = getAction(method);
                sysLog.setAction(action);

                sysLogService.save(sysLog);
            }
            //2.取出执行方法所需的参数
            Object[] args = pjp.getArgs();
            //3.执行方法
            rtValue = pjp.proceed(args);
        }catch (Throwable t){
            t.printStackTrace();
        }
        //4.返回
        return rtValue;
    }

    /**
     * 获取action的内容
     * @param method
     * @return
     */
    private String getAction(Method method){
        //1.判断方法上有没有我想要的注解：GetMapping,PostMapping,PutMapping,DeleteMapping RequestMapping
        if(method.isAnnotationPresent(GetMapping.class)){
            //2.取出方法上的注解
            GetMapping getMapping = method.getAnnotation(GetMapping.class);
            //3.获取name属性
            return  getMapping.name();
        }

        if(method.isAnnotationPresent(PostMapping.class)){
            //2.取出方法上的注解
            PostMapping getMapping = method.getAnnotation(PostMapping.class);
            //3.获取name属性
            return  getMapping.name();
        }

        if(method.isAnnotationPresent(PutMapping.class)){
            //2.取出方法上的注解
            PutMapping getMapping = method.getAnnotation(PutMapping.class);
            //3.获取name属性
            return  getMapping.name();
        }

        if(method.isAnnotationPresent(DeleteMapping.class)){
            //2.取出方法上的注解
            DeleteMapping getMapping = method.getAnnotation(DeleteMapping.class);
            //3.获取name属性
            return  getMapping.name();
        }
        if(method.isAnnotationPresent(RequestMapping.class)){
            //2.取出方法上的注解
            RequestMapping getMapping = method.getAnnotation(RequestMapping.class);
            //3.获取name属性
            return  getMapping.name();
        }
        return null;
    }
}
